<!--有控件的表头组件 -->
<template>
  <a-modal
    :width="'80%'"
    :visible="dialogVisible"
    @ok="handleOk"
    @cancel="handleCancel"
    unmountOnClose
    title-align="center"
  >
    <template #title> {{ props.title }} </template>

    <div class="wrap">
      <div class="wrap-unused">
        <a-scrollbar style="height: 600px; overflow: auto">
          <a-space direction="vertical">
            <h3>可选字段</h3>

            <a-checkbox
              :model-value="checkedAll"
              :indeterminate="indeterminate"
              @change="handleChangeAll"
              >全选
            </a-checkbox>
            <div v-for="item in headerList.list" :key="item.collectionCode">
              <h3>{{ item.collectionName }}</h3>
              <a-checkbox-group @change="onChange" v-model="selectedData">
                <a-checkbox
                  class="checkItem"
                  v-for="controls in item.heads"
                  :key="controls?.ctlCode"
                  :value="controls?.ctlCode"
                  :disabled="forbidList.includes(controls?.ctlCode)"
                >
                  <span :title="controls.ctlCnName">
                    {{ controls.ctlCnName }}
                  </span>
                </a-checkbox>
              </a-checkbox-group>
            </div>
          </a-space>
        </a-scrollbar>
      </div>
      <div class="wrap-used">
        <a-scrollbar style="height: 600px; overflow: auto">
          <div class="draggable-selected">
            <h3>已选字段</h3>
            <a-space
              direction="vertical"
              class="item-box"
              :size="16"
              v-for="element in selectedHeader.list?.filter((el: any) => forbidList.includes(el?.ctlCode))"
              :key="element?.ctlCode"
            >
              <div class="item-box-container">
                <icon-font
                  type="icon-a-Dragtuozhuai"
                  :size="16"
                  v-if="!forbidList.includes(element?.ctlCode)"
                ></icon-font>
                <span
                  :style="{
                    marginLeft: '10px'
                  }"
                >
                  <span :title="element.ctlCnName">
                    {{ element.ctlCnName }}</span
                  >
                </span>
                <a-tooltip content="删除" position="left">
                  <icon-font
                    type="icon-a-Close-smallguanbi-xiao"
                    :size="20"
                    @click="removeHeader(element)"
                    v-if="!forbidList.includes(element?.ctlCode)"
                    :style="{
                      float: 'right',
                      transform: 'translateY(-50%)',
                      margin: '25px 10px 0px 0px',
                      cursor: 'pointer'
                    }"
                  ></icon-font>
                </a-tooltip>

                <a-tooltip content="置底">
                  <icon-to-bottom
                    :style="{
                      float: 'right',
                      transform: 'translateY(-50%)',
                      margin: '25px 10px 0px 0px',
                      cursor: 'pointer'
                    }"
                    @click="moveBottom(element)"
                    v-if="!forbidList.includes(element?.ctlCode)"
                  />
                </a-tooltip>
                <a-tooltip content="置顶">
                  <icon-to-top
                    :style="{
                      float: 'right',
                      transform: 'translateY(-50%)',
                      margin: '25px 10px 0px 0px',
                      cursor: 'pointer'
                    }"
                    @click="moveTop(element)"
                    v-if="!forbidList.includes(element?.ctlCode)"
                  />
                </a-tooltip>
              </div>
            </a-space>
            <draggable
              class="item"
              :list="selectedHeader.list"
              ghost-class="ghost"
              handle=".move"
              filter=".forbid"
              :force-fallback="true"
              chosen-class="chosenClass"
              animation="300"
              :fallback-class="true"
              :fallback-on-body="true"
              :touch-start-threshold="10"
              :fallback-tolerance="10"
              :sort="true"
              itemKey="code"
            >
              <template #item="{ element }">
                <a-space
                  direction="vertical"
                  class="item-box"
                  :size="16"
                  v-if="!forbidList.includes(element.ctlCode)"
                >
                  <div class="item-box-container move">
                    <icon-font
                      type="icon-a-Dragtuozhuai"
                      :size="16"
                    ></icon-font>
                    <span
                      :style="{
                        marginLeft: '10px'
                      }"
                    >
                      {{ element.ctlCnName }}
                    </span>
                    <a-tooltip content="删除" position="left">
                      <icon-font
                        type="icon-a-Close-smallguanbi-xiao"
                        :size="20"
                        @click="removeHeader(element)"
                        v-if="
                          forbidList.includes(element?.ctlCode) ? false : true
                        "
                        :style="{
                          float: 'right',
                          transform: 'translateY(-50%)',
                          margin: '25px 10px 0px 0px',
                          cursor: 'pointer'
                        }"
                      ></icon-font>
                    </a-tooltip>
                    <a-tooltip content="置底">
                      <icon-to-bottom
                        :style="{
                          float: 'right',
                          transform: 'translateY(-50%)',
                          margin: '25px 10px 0px 0px',
                          cursor: 'pointer'
                        }"
                        @click="moveBottom(element)"
                      />
                    </a-tooltip>
                    <a-tooltip content="置顶">
                      <icon-to-top
                        :style="{
                          float: 'right',
                          transform: 'translateY(-50%)',
                          margin: '25px 10px 0px 0px',
                          cursor: 'pointer'
                        }"
                        @click="moveTop(element)"
                      />
                    </a-tooltip>
                  </div>
                </a-space>
              </template>
            </draggable>
          </div>
        </a-scrollbar>
      </div>
    </div>
    <template #footer>
      <a-button @click="handleCancel">取消</a-button>
      <a-button type="primary" @click="handleOk" :loading="store.getIsLoading"
        >确定</a-button
      >
    </template>
  </a-modal>
</template>

<script lang="ts" setup>
import { reactive, ref, computed, watch, watchEffect } from 'vue';
import { formHeaderSetting } from '@/types/global';
import Draggable from 'vuedraggable';
import cloneDeep from 'lodash.clonedeep';
import useGlobalParametersStore from '@/store/modules/globalParameters';

const store = useGlobalParametersStore();
const props = withDefaults(
  // 参数说明
  defineProps<{
    visible: boolean; // 判断是否打开表头设置抽屉
    title: string; // 标题

    /*
      filedName: string;
      name: string;
      isDefault: boolean;
      sort: number;
    */
    resultList: any; // 传过来的表头
    forbidList?: string[]; // 不准移动和删除的表头
    orginHeaderList?: string[]; // 后端传过来的表头数据
    // listData: () => any; // 请求表头的数据
  }>(),
  {
    visible: false,
    title: '表头设置',
    resultList: () => [],
    forbidList: () => []
  }
);

const emits = defineEmits(['update:visible', 'headerSave']);

// 单个表头接口
type Iheader = {
  id?: number; // id
  ctlCode: string; // 控件编码
  isDefault: boolean; // 是否选择表头
  code: string; // 表头编号
  name: string; // 表头名称
};

// 判断抽屉是否显示
const dialogVisible = computed({
  get() {
    return props.visible;
  },
  set(visible: boolean) {
    emits('update:visible', visible);
  }
});

const checkedAll = ref(false); // 判断是否全选
const indeterminate = ref(false);
let selectedData: any = ref([]); // 储存多选框选中的值
// 所有表头
const headerList: any = reactive({
  list: []
});

// 未选择的表头
const unselectedHeaders: any = reactive({
  list: []
});

// 选择的表头
const selectedHeader: any = reactive({
  list: []
});

// 判断全选按钮的状态;
const isIndeterminate = () => {
  if (selectedData.value.length === tempArr.value.length) {
    checkedAll.value = true;
    indeterminate.value = false;
  } else if (selectedData.value.length === 0) {
    checkedAll.value = false;
    indeterminate.value = false;
  } else {
    checkedAll.value = false;
    indeterminate.value = true;
  }
};

let tempArr: any = ref([]); // 储存所有表头
watch(
  dialogVisible,
  (newVal, oldVal) => {
    if (newVal) {
      headerList.list = cloneDeep(props.resultList);
      unselectedHeaders.list = [];
      selectedHeader.list = [];
      tempArr.value = [];

      let defaultHeaders = props?.orginHeaderList.split(','); // 默认从后端传过来的表头

      let forbidArr = []; // 储存禁止移动的表头的详细数据
      headerList.list.forEach((item1: any) => {
        unselectedHeaders.list = [
          ...unselectedHeaders.list,
          ...item1.heads?.filter((item2: any) => item2.isDefault === false)
        ];
        tempArr.value = [...tempArr.value, ...item1.heads];

        forbidArr = [
          ...forbidArr,
          item1.heads?.filter((el: any) =>
            props?.forbidList.includes(el.ctlCode)
          )
        ];
      });

      defaultHeaders.forEach((item: any) => {
        const temp = tempArr.value.find((el: any) => el.ctlCode === item);
        selectedHeader.list.push(temp);
      });

      // 先将禁止移动的表头重复放到最前面，然后再去重，这样禁止移动的表头就在最前面了
      headerList.list.forEach((el: any, ind: number) => {
        for (let i = forbidArr[ind].length - 1; i >= 0; i--) {
          el.heads.unshift(forbidArr[ind][i]);
        }
        el.heads = el.heads.reduce((accumulator, currentValue) => {
          if (
            !accumulator.find((item) => item.ctlCode === currentValue.ctlCode)
          ) {
            accumulator.push(currentValue);
          }
          return accumulator;
        }, []);
      });
      selectedHeader.list = selectedHeader.list.reduce(
        (accumulator, currentValue) => {
          if (
            !accumulator.find((item) => item.ctlCode === currentValue.ctlCode)
          ) {
            accumulator.push(currentValue);
          }
          return accumulator;
        },
        []
      );
      selectedData.value = [];
      selectedData.value = selectedHeader.list.map((el: any) => el.ctlCode);
      isIndeterminate();
      console.log('==========forbidArrforbidArr==========================');
      console.log(selectedHeader.list);
      console.log(forbidArr);
      console.log('====================================');
    } else headerList.list = [];
  },
  {
    immediate: true
  }
);

// 全选事件
const handleChangeAll = (value: boolean) => {
  indeterminate.value = false;
  if (value) {
    selectedData.value = [];
    selectedHeader.list = [];
    checkedAll.value = true;
    headerList.list.forEach((item: any) => {
      item.heads.forEach((item2: any) => {
        item2.isDefault = true;
        selectedData.value.push(item2.ctlCode);
        selectedHeader.list.push(item2);
      });
    });
  } else {
    checkedAll.value = false;
    selectedHeader.list = [];
    selectedData.value = [];
    headerList.list.forEach((item: any) => {
      item.heads.forEach((item2: any) => {
        if (props.forbidList.includes(item2.ctlCode)) {
          item2.isDefault = true;
          selectedHeader.list.push(item2);
          selectedData.value.push(item2.ctlCode);
        } else item2.isDefault = false;
      });
    });
  }
};

// 点击非全选框时
const onChange = (val: any) => {
  isIndeterminate();
  headerList.list.forEach((item: any) => {
    item.heads.forEach((item2: any) => {
      if (val.includes(item2.ctlCode)) item2.isDefault = true;
      else item2.isDefault = false;

      // 新增
      if (val.length > selectedHeader.list.length) {
        if (item2.ctlCode === val[val.length - 1]) {
          selectedHeader.list.push(item2);
        }
      }
      // 删除
      else {
        let removeInd = -1;
        selectedHeader.list.forEach((el: any, ind: number) => {
          if (!val.includes(el.ctlCode)) {
            removeInd = ind;
          }
        });
        if (removeInd !== -1) {
          selectedHeader.list.splice(removeInd, 1);
        }
      }
    });
  });
};

// 置底
const moveBottom = (element: any) => {
  const ind = selectedHeader.list.findIndex(
    (item: any) => item.ctlCode === element.ctlCode
  );
  selectedHeader.list.push(selectedHeader.list.splice(ind, 1)[0]);
};

// 置顶
const moveTop = (element: any) => {
  const ind = selectedHeader.list.findIndex(
    (item: any) => item.ctlCode === element.ctlCode
  );
  let ind2 = -1;
  for (let i = 0; i < selectedHeader.list.length; i++) {
    if (props.forbidList.includes(selectedHeader.list[i].ctlCode)) {
      ind2 = i;
    }
  }
  if (ind !== -1 && ind2 !== -1) {
    const newList = [...selectedHeader.list]; // 使用解构赋值创建一个新的数组副本
    // 插入到最前面
    newList.splice(0, 0, newList.splice(ind, 1)[0]);

    // [newList[ind], newList[ind2 + 1]] = [newList[ind2 + 1], newList[ind]]; // 交换两个元素的位置
    selectedHeader.list = newList; // 更新原始数组
  }
};

// 去除一个表头
const removeHeader = (header: Iheader) => {
  headerList.list.forEach((item1: any) => {
    item1.heads.forEach((item2: any) => {
      if (item2.ctlCode === header.ctlCode) {
        item2.isDefault = false;
        const index = selectedData.value.findIndex(
          (item3: any) => item3 === header.ctlCode
        );
        selectedData.value.splice(index, 1);

        const ind = selectedHeader.list.findIndex(
          (el: any) => el.ctlCode === header.ctlCode
        );
        selectedHeader.list.splice(ind, 1);
        isIndeterminate();
      }
    });
  });
};

// 确认
const handleOk = () => {
  // 排序
  // selectedHeader.list.forEach((item: any, index: number) => {
  //   item.sort = index + 1;
  // });
  // 获取当前用户的id
  // const userId: any = +(localStorage.getItem('userId') as string);
  emits(
    'headerSave',
    headerList.list,
    selectedHeader.list,
    unselectedHeaders.list
    // userId
  );
  dialogVisible.value = false;
};

// 取消
const handleCancel = () => {
  dialogVisible.value = false;
};
</script>

<style scoped lang="less">
.wrap {
  display: flex;
  justify-content: space-between;

  &-unused {
    flex: 4;
    border: 1px solid #ccc;
    margin-right: 10px;
    height: 600px;
    padding: 10px;

    // 六个字的宽度，如果超过则显示省略号
    .checkItem {
      display: inline-block;
      width: 8em; /* 六个字的宽度 */
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }

  &-used {
    flex: 2;
    border: 1px solid #ccc;
    padding: 10px;
    .draggable {
      &-selected {
        padding-bottom: 20px;

        .item {
          &-box {
            width: 100%;
            &-container {
              // background-color: #f2f3f5;
              height: 50px;
              line-height: 50px;
            }
            &-container:hover {
              background-color: #f2f3f5;
            }
          }
        }
      }
      // &-unselected {
      //   .item {
      //     display: flex;
      //     flex-wrap: wrap;
      //     width: 100%;
      //     background-color: #4e5969;
      //     &-box {
      //       width: 100%;
      //       margin: 0 10px 10px 0;
      //       &-container {
      //         background-color: #f2f3f5;
      //       }
      //     }
      //   }
      // }
    }
  }
}
</style>
